﻿using System.Data.SQLite;
using System.IO;
using CompactMapper.Orm.UnitOfWork.Commands.Implementations;

namespace CompactMapper.Orm.UnitOfWork.Mappings
{
    internal class CreationMappings : CommandMappingsBase
    {
        public CreationMappings(TablesTree tablesTree)
            : base(tablesTree)
        {
        }

        protected override void CreateSpecificMappings(Tree<Table> tablesTree)
        {
            foreach (var childItem in tablesTree.Children)
            {
                if (childItem.Node.CreateTableCommand == null)
                {
                    childItem.Node.CreateTableCommand = new CreateTableCommand(childItem.Node, TablesTree);
                }
                CreateSpecificMappings(childItem);
            }
        }

        public void Run(SQLiteConnection connection)
        {
            Recreate(TablesTree);
            RunCommands(TablesTree, connection);
        }

        private static void Recreate(Tree<Table> commandsTree)
        {
            commandsTree.Node.AlreadyCreated = false;
            foreach (var command in commandsTree.Children)
            {
                Recreate(command);
            }
        }

        private static void RunCommands(Tree<Table> commandsTree, SQLiteConnection connection)
        {
            if (commandsTree.Node.AlreadyCreated)
                return;
            commandsTree.Node.AlreadyCreated = true;
            commandsTree.Node.CreateTableCommand.Run(connection);
            foreach (var command in commandsTree.Children)
            {
                RunCommands(command, connection);
            }
        }


        public void DumpSchema(MemoryStream stream)
        {
            var writer = new StreamWriter(stream);
            RunOutputSql(TablesTree, writer);
            writer.Flush();
        }

        private static void RunOutputSql(Tree<Table> commandsTree, StreamWriter output)
        {
            commandsTree.Node.CreateTableCommand.OutputSql(output);
            foreach (var command in commandsTree.Children)
            {
                RunOutputSql(command, output);
            }
        }
    }
}